/*global window: false, soundManager: false*/
/*
 * #depends subsonic-login.js
 */
Ext.ns('Ext.ux.mattgoldspink.subsonic.controllers');

Ext.ux.mattgoldspink.subsonic.controllers.Player = function(){
    // setup msg bus
    this.msgbus = new Ext.ux.MsgBus();
    this.msgbus.init(this);
    this.subscribe('subsonic.player.play.playlist', {
        scope: this,
        fn: this.playTracks
    });
    this.subscribe('subsonic.player.play', {
        scope: this,
        fn: this.resumeCurrent
    });
    this.subscribe('subsonic.player.pause', {
        scope: this,
        fn: this.pauseCurrent
    });
    this.subscribe('subsonic.player.stop', {
        scope: this,
        fn: this.stopCurrent
    });
    this.subscribe('subsonic.player.forward', {
        scope: this,
        fn: this.skipCurrent
    });
    this.subscribe('subsonic.player.back', {
        scope: this,
        fn: this.skipBackward
    });
    this.subscribe('subsonic.player.skipto', {
        scope: this,
        fn: this.skipInto
    });
    this.subscribe('subsonic.player.volume.set', {
        scope: this,
        fn: this.setVolume
    });
    this.subscribe('subsonic.player.internal.doOnFinish', {
        scope: this,
        fn: this.doOnFinish
    });
    this.subscribe('subsonic.player.shuffle.toggle', {
        scope: this,
        fn: this.doShuffleToggle
    });
    this.subscribe('subsonic.player.repeat', {
        scope: this,
        fn: this.handleRepeat
    });
};

/**
 * Player controller
 * Publishes:
    subsonic.track.playlist
    subsonic.track.nowplaying
    subsonic.track.skippedTo
    subsonic.track.stopped
    subsonic.track.volume.change
 * Subscribes to:
    subsonic.player.start
    subsonic.player.stop
    subsonic.player.forward
    subsonic.player.back
    subsonic.player.skipto
    subsonic.player.volume.set
 */
Ext.apply(Ext.ux.mattgoldspink.subsonic.controllers.Player.prototype, {
    playbuttons: [],
    currentPlaylist: [],
    currentTrackId: undefined,
    volume: undefined,
	shuffle: false,
	repeatMode: 'off',
    setVolume: function(subject, value){
        this.volume = value;
        if (Ext.isDefined(this.currentTrackId)) {
            soundManager.setVolume(this.currentTrackId, value);
        }
        Ext.each(this.currentPlaylist, function(track){
            track.setVolume(value);
        });
    },
    playTracks: function(subject, options) {
        var tracks = options.tracks, startAtTrack = options.startAtTrack;
        this.disposeOfCurrent();
        tracks.each(function(track, index) {
            var id = track.get('id');
            var sound = soundManager.createSound({
                id: 'music' + id,
                url: Ext.ux.mattgoldspink.subsonic.apiUrl + '/rest/stream.view?' + Ext.urlEncode(Ext.ux.mattgoldspink.subsonic.LoginDetails) +'&id='+id,
                autoLoad: (index === startAtTrack),
                autoPlay: (index === startAtTrack),
                trackdata: track.data,
                onplay: this.handleOnPlay,
                onresume: this.handleOnPlay,
                onpause: this.handleOnPause,
                onfinish: this.handleOnFinish,
                onstop: this.handleOnStop,
                whileplaying: this.handleWhilePlaying,
                volume: this.volume
            });
            if (index === startAtTrack){
                this.currentTrackId = 'music' + id;
            }
            this.currentPlaylist.push(sound);
        }, this);
    },
    disposeOfCurrent: function(){
        Ext.each(this.currentPlaylist, function(track){
            try {
                track.stop();
                track.destruct();
            } catch(e) {
            }
        });
        this.currentPlaylist = [];
    },
    skipInto: function(subject, position) {
        soundManager.setPosition(this.currentTrackId, position * 1000);
    },
    resumeCurrent: function(){
        if (Ext.isDefined(this.currentTrackId) && Ext.isDefined(this.currentPlaylist)){
            var current = soundManager.getSoundById(this.currentTrackId);
            if(current.playState === 0) {
                current.play();
            } else {
                current.resume();    
            }
            current.setVolume(this.volume);
        }
    },
    pauseCurrent: function(){
        soundManager.pause(this.currentTrackId);
    },
    stopCurrent: function(){
        soundManager.stop(this.currentTrackId);
    },
    skipCurrent: function() {
        if (Ext.isDefined(this.currentTrackId) && Ext.isDefined(this.currentPlaylist)){
            var current = soundManager.getSoundById(this.currentTrackId);
            if (!current.paused) {
                current.stop();
            }
            this.doOnFinish('', current, true);
        }
    },
    skipBackward: function() {
        if (Ext.isDefined(this.currentTrackId) && Ext.isDefined(this.currentPlaylist)){
            // if more than 3 sec in restart song
            var current = soundManager.getSoundById(this.currentTrackId);
            if (current.position /1000 > 3) {
                soundManager.setPosition(this.currentTrackId, 0);
            } else {
                for (var i = 0; i < this.currentPlaylist.length; i++) {
                    var track = this.currentPlaylist[i];
                    if (track === current) {
                        if (i-1 > -1) {
                            var nextTrack = this.currentPlaylist[i-1];
                            soundManager.stop(this.currentTrackId);
                            soundManager.play(nextTrack.sID);
                            this.currentTrackId = nextTrack.sID;
                        return;
                        } else {
                            soundManager.setPosition(this.currentTrackId, 0);
                        }
                    }
                }
            }
        }
    },
    handleOnPlay: function(){
        this.setVolume(this.volume);
        window.Ext.ux.Bus.fireEvent('message', 'subsonic.track.nowplaying', this.options.trackdata);
    },
    handleOnPause: function() {
        window.Ext.ux.Bus.fireEvent('message', 'subsonic.track.paused', this.options.trackdata);
    },
    handleOnStop: function() {
        window.Ext.ux.Bus.fireEvent('message', 'subsonic.track.stopped', this.options.trackdata);
    },
    handleWhilePlaying: function(){
        window.Ext.ux.Bus.fireEvent('message', 'subsonic.track.whileplaying', this.position);
    },
    doOnFinish: function(subject, doneTrack, skipping){
		var nextTrack;
		if (!skipping && this.repeatMode === 'one') {
			nextTrack = doneTrack;
		} else if (!this.shuffle) {
			for (var i = 0; i < this.currentPlaylist.length; i++) {
				var track = this.currentPlaylist[i];
				if (track === doneTrack && i+1 < this.currentPlaylist.length) {
					nextTrack = this.currentPlaylist[i+1];
					break;
				}
			}
			if (nextTrack === undefined && this.repeatMode === 'all') {
				nextTrack = this.currentPlaylist[0];
			}
		} else {
			var total = this.currentPlaylist.length, nextIndex = Math.floor(Math.random()*total);
			nextTrack = this.currentPlaylist[nextIndex];
		}
		if (!doneTrack.paused) {
			if (!skipping || (skipping && doneTrack.playState !== 1)) {
				if (!skipping) {
					this.handleOnStop.apply(doneTrack, []);
				}
				if (nextTrack) {
					nextTrack.play();
				}
			}
		} else {
			if (doneTrack.playState === 0) {
				this.handleOnStop.apply(doneTrack, []);
			} else {
				doneTrack.stop();
			}
			if (nextTrack) {
				nextTrack.load();
				nextTrack.pause();
			}
		}
		if (nextTrack) {
			this.currentTrackId = nextTrack.sID;
		} else {
			this.currentTrackId = this.currentPlaylist[0].sID;
		}
    },
    handleOnFinish: function() {
        window.Ext.ux.Bus.fireEvent('message', 'subsonic.player.internal.doOnFinish', this);
    },
	doShuffleToggle: function(subject, data) {
		this.shuffle = !this.shuffle;
	},
	handleRepeat: function(subject, data) {
		this.repeatMode = data;
	}
});
Ext.ux.mattgoldspink.subsonic.controllers.Player.singleton = new Ext.ux.mattgoldspink.subsonic.controllers.Player();